package top.infopub.mgc.wsImpl;


import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import top.infopub.common.ErrorCodeEnum;
import top.infopub.concurrent.ExecutorManager;
import top.infopub.dubbo.vo.mgc.MsgSenderRoleVo;
import top.infopub.dubbo.vo.mgc.MsgSenderVo;
import top.infopub.dubbo.ws.mgc.MsgSenderService;
import top.infopub.mgc.core.domain.SysOperatorDomain;
import top.infopub.mgc.core.domain.TemplateInfo;
import top.infopub.mgc.core.sender.email.EmailSenderProxy;
import top.infopub.mgc.core.sender.sms.SmsSenderProxy;
import top.infopub.mgc.core.service.MsgTaskService;
import top.infopub.mgc.core.service.MsgTemplateService;
import top.infopub.mgc.exception.TemplatParseException;
import top.infopub.model.mgc.MsgTask;
import top.infopub.vo.ResponseVo;
import freemarker.template.Template;


/**
 * 消息发送  ws接口
 * @author Awoke
 * @version 2018年11月6日
 * @see WsMsgSenderServiceImpl
 * @since
 */
@Service
public class WsMsgSenderServiceImpl implements MsgSenderService {

    private static final Logger logger = LoggerFactory.getLogger(WsMsgSenderServiceImpl.class);

    @Autowired
    private MsgTemplateService msgTemplateService;

    @Autowired
    private MsgTaskService msgTaskService;

    @Autowired
    private SmsSenderProxy smsSenderProxy;

    @Autowired
    private EmailSenderProxy emailSenderProxy;

    @SuppressWarnings("unchecked")
    @Override
    public ResponseVo<String> send(MsgSenderVo sendVo) {
        if (sendVo == null || StringUtils.isBlank(sendVo.getTemplateMainCode())) {
            return ErrorCodeEnum.ERROR_COMMON_PARAM.getResponseVo();
        }
        // 不允许批量发送短信
        if (StringUtils.contains(sendVo.getTelNo(), ",")) {
            return ErrorCodeEnum.ERROR_MGC_MULTI_PHONES.getResponseVo();
        }
        // 一个mainCode可以对应多个TemplateInfo
        HashSet<TemplateInfo> tinfos = msgTemplateService.selectTemplatesByMainCode(sendVo.getTemplateMainCode());
        if (tinfos == null) {
            return ErrorCodeEnum.ERROR_MGC_TEMPLATE.getResponseVo();
        }
        for (TemplateInfo tinfo : tinfos) {
            try {
                // 短信模板
                if (tinfo.getSpartnerType() != null && tinfo.getSpartnerType() == 1) {
                    // 生成消息内容
                    String content = generatorTemplateContent(tinfo.getTemplateObj(),
                        sendVo.getContentParam());
                    content = StringEscapeUtils.unescapeHtml4(content);
                    // 无手机号码则不发送短信
                    if (StringUtils.isBlank(sendVo.getTelNo())) {
                        continue;
                    }
                    final MsgTask msgTask = new MsgTask();
                    msgTask.setAddtime(new Date());
                    msgTask.setUpdatetime(new Date());
                    msgTask.setSpartnerId(tinfo.getSpartnerId());
                    msgTask.setSenderTemplateId(tinfo.getId());
                    // 1：实时 2 ：延时  这里统一设置为实时 
                    msgTask.setIsRealtime(1);
                    // 收件人
                    msgTask.setMsgRecipient(sendVo.getTelNo());
                    // 标题
                    msgTask.setTitle(tinfo.getTemplateTitle());
                    // 内容
                    msgTask.setContent(content);
                    msgTask.setMsgSourceSystem(sendVo.getSourceSystem());
                    // 消息类型  1： 短信 2：邮件
                    msgTask.setMsgType(1);
                    // 消息状态 1：待发送 2：正在发送 3：发送成功 4：发送失败 ，这里初始状态设置为1
                    msgTask.setState(1);
                    // 发送类别 1：单发 2：群发  这里一定是单发
                    msgTask.setSenderType(1);
                    // 0：启用 1：删除
                    msgTask.setDelFlag(0);
                    // 模板分类code
                    msgTask.setTemplateCode(tinfo.getTempTypeCode());
                    // 发送过程中 的超时时间  默认1分钟
                    try {
                        msgTask.setTimeout(StringUtils.isBlank(tinfo.getTimeout()) ? BigDecimal.ONE : new BigDecimal(
                            tinfo.getTimeout()));
                    }
                    catch (Exception e) {
                        msgTask.setTimeout(BigDecimal.ONE);
                    }
                    msgTaskService.insert(msgTask);
                    // 调用异步发送 >>
                    ExecutorManager.getInstance().execute(new Runnable() {
                        @Override
                        public void run() {
                            smsSenderProxy.sendMessage(msgTask);
                        }
                    });
                }
                // 邮件模板
                else if (tinfo.getSpartnerType() != null && tinfo.getSpartnerType() == 2) {
                    // 处理map-para
                    Map<String, Object> _ts = new HashMap<String, Object>();
                    Map<String, Object> _values = sendVo.getContentParam();
                    if (_values != null) {
                        for (Entry<String, Object> _vs : _values.entrySet()) {
                            if (_vs.getValue() != null && (_vs.getValue() instanceof String)) {
                                _ts.put(_vs.getKey(),
                                    StringEscapeUtils.escapeHtml4(_vs.getValue().toString()));
                            }
                            else {
                                _ts.put(_vs.getKey(), _vs.getValue());
                            }
                        }
                    }
                    // 生成消息内容
                    String content = generatorTemplateContent(tinfo.getTemplateObj(), _ts);
                    // 无邮箱则不发送邮件
                    if (StringUtils.isBlank(sendVo.getMailAddress())) {
                        continue;
                    }
                    final MsgTask msgTask = new MsgTask();
                    msgTask.setAddtime(new Date());
                    msgTask.setUpdatetime(new Date());
                    msgTask.setSpartnerId(tinfo.getSpartnerId());
                    msgTask.setSenderTemplateId(tinfo.getId());
                    // 1：实时 2 ：延时  这里统一设置为实时 
                    msgTask.setIsRealtime(1);
                    // 收件人
                    msgTask.setMsgRecipient(sendVo.getMailAddress());
                    msgTask.setTitle(tinfo.getTemplateTitle());
                    msgTask.setContent(content);
                    // 附件
                    msgTask.setAttach(sendVo.getAttachLocation());
                    msgTask.setMsgSourceSystem(sendVo.getSourceSystem());
                    msgTask.setMsgType(2);
                    // 消息状态 1：待发送 2：正在发送 3：发送成功 4：发送失败 ，这里初始状态设置为1
                    msgTask.setState(1);
                    // 发送类别 1：单发 2：群发
                    msgTask.setSenderType(sendVo.getMailAddress().contains(",") ? 2 : 1);
                    msgTask.setDelFlag(0);
                    // 模板分类code
                    msgTask.setTemplateCode(tinfo.getTempTypeCode());
                    // 发送过程中 的超时时间  默认1分钟
                    try {
                        msgTask.setTimeout(StringUtils.isBlank(tinfo.getTimeout()) ? BigDecimal.ONE : new BigDecimal(
                            tinfo.getTimeout()));
                    }
                    catch (Exception e) {
                        msgTask.setTimeout(BigDecimal.ONE);
                    }
                    msgTaskService.insert(msgTask);
                    // 调用异步发送 >>
                    ExecutorManager.getInstance().execute(new Runnable() {
                        @Override
                        public void run() {
                            emailSenderProxy.sendMail(msgTask);
                        }
                    });
                }
            }
            catch (Exception e) {
                logger.error("send error, sendVo info:" + sendVo, e);
            }
        }
        return ResponseVo.getSuccessResponse();
    }

    @SuppressWarnings("unchecked")
    @Override
    public ResponseVo<String> send(MsgSenderVo... sendVos) {
        if (sendVos == null || sendVos.length == 0) {
            return ErrorCodeEnum.ERROR_COMMON_PARAM.getResponseVo();
        }
        for (MsgSenderVo sendVo : sendVos) {
            if (StringUtils.isBlank(sendVo.getTemplateMainCode())) {
                return ErrorCodeEnum.ERROR_COMMON_PARAM.getResponseVo();
            }
        }
        if (sendVos.length == 1) {
            return send(sendVos[0]);
        }
        for (MsgSenderVo sendVo : sendVos) {
            send(sendVo);
        }
        return ResponseVo.getSuccessResponse();
    }

    @SuppressWarnings("unchecked")
    @Override
    public ResponseVo<String> sendRole(MsgSenderRoleVo vo) {
        if (vo == null || StringUtils.isBlank(vo.getPurviewCode())
            || StringUtils.isBlank(vo.getTemplateMainCode())) {
            return ErrorCodeEnum.ERROR_COMMON_PARAM.getResponseVo();
        }
        List<SysOperatorDomain> _res = msgTemplateService.selectUsersByPurCode(vo.getPurviewCode());
        if (_res == null || _res.isEmpty()) {
            return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("无对应权限的用户");
        }
        // 转成MsgSenderVo
        Set<MsgSenderVo> lists = new HashSet<>();
        for (SysOperatorDomain re : _res) {
            MsgSenderVo senderVo = new MsgSenderVo();
            // 手机号码
            senderVo.setTelNo(re.getSmobile());
            // 邮箱
            senderVo.setMailAddress(re.getEmail());
            // 邮件附件
            senderVo.setAttachLocation(vo.getAttachLocation());
            senderVo.setContentParam(vo.getContentParam());
            senderVo.setTemplateMainCode(vo.getTemplateMainCode());
            lists.add(senderVo);
        }
        return send(lists.toArray(new MsgSenderVo[lists.size()]));
    }

    /** 生成消息内容  **/
    private String generatorTemplateContent(Template templateObj, Map<String, Object> params) {
        try {
            return FreeMarkerTemplateUtils.processTemplateIntoString(templateObj, params);
        }
        catch (Exception e) {
            throw new TemplatParseException(e);
        }
    }

}
